package com.example.demo.servcie.impl;

import com.example.demo.model.DataCleaning;
import com.example.demo.model.ImportCleaning;
import com.example.demo.servcie.DataImportService;
import com.example.demo.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @author Liunh
 */
@Slf4j
@Service
public class CleaningServiceImpl implements DataImportService {

    @Resource(name = "taskExecutor")
    private ThreadPoolTaskExecutor taskExecutor;


    @Override
    public Result<String> importData(Integer userId, String batchNo, MultipartFile file, HttpServletResponse response) {
        final Date startTime = DateUtil.getCurrentDate();
        final Result<String> result = new Result<String>().invokeSuccess(null, "导入清理数据成功！");
        final List<ImportCleaning> importFailList = new ArrayList<>();
        final List<ImportCleaning> importList = new ArrayList<>();
        try {
            //获取导入数据
            importList.addAll(Objects.requireNonNull(ExcelUtil.getInstance().importExcel(file.getInputStream(), 0, 1, ImportCleaning.class)));
        } catch (Exception e) {
            importFailList.addAll(importList);
            log.error("导入数据清理模本错误！", e);
            result.invokeFail("导入数据清理模本错误！");
        }
        //保存导入数据
        Integer amount = null;
        log.info(">>>>>> importList", JacksonUtil.beanToJson(importList));
        if (CollectionUtils.isEmpty(importFailList) && CollectionUtils.isNotEmpty(importList)) {
            amount = importList.size();
            Map<Integer, List<ImportCleaning>> multiList = CollectionUtil.getInstance().toMultiList(importList, 2000);
            log.info(">>>>>> multiList", JacksonUtil.beanToJson(multiList));
            for (Map.Entry<Integer, List<ImportCleaning>> entry : multiList.entrySet()) {
                List<ImportCleaning> tmpList = entry.getValue();
                try {
                    FutureTask<Result<List<ImportCleaning>>> futureTask = new FutureTask<>(new ImportCleaningThread(tmpList, userId, batchNo));
                    taskExecutor.execute(futureTask);
                    Result<List<ImportCleaning>> futureTaskResult = futureTask.get();
                    taskExecutor.shutdown();
                    if (!futureTaskResult.isSuccess()) {
                        importFailList.addAll(futureTaskResult.getData());
                    }
                } catch (ExecutionException | InterruptedException e) {
                    importFailList.addAll(tmpList);
                    result.invokeFail("数据清理导入线程处理异常！");
                    log.error("数据清理导入线程处理异常！", e);
                }
            }
        }
        try {
            // logService保存异常数据
            if (CollectionUtils.isNotEmpty(importFailList)) {
                Integer finalAmount = amount;

                //异常数据生成Excel文件
                result.setData("exportUrl");
            }
        } catch (Exception e) {
            result.invokeFail("清理日志数据导出异常！");
            log.error("清理日志数据导出异常！", e);
        }
        return result;
    }


    class ImportCleaningThread implements Callable<Result<List<ImportCleaning>>> {

        private final List<ImportCleaning> tmpList;
        private String batchNo;
        private Integer userId;

        public ImportCleaningThread(List<ImportCleaning> tmpList, Integer userId, String batchNo) {
            this.tmpList = tmpList;
            this.batchNo = batchNo;
            this.userId = userId;
        }

        @Override
        public Result<List<ImportCleaning>> call() throws Exception {
            log.info("图书清理数据导入线程" + Thread.currentThread().getName());
            final Result<List<ImportCleaning>> result = new Result<List<ImportCleaning>>().invokeSuccess(null, "图书清理数据导入成功！");
            final List<ImportCleaning> importFailList = new ArrayList<>();
            if (CollectionUtils.isNotEmpty(tmpList)){
                for (int i = 0; i < tmpList.size(); i++) {
                    tmpList.forEach(o -> {
                        DataCleaning cleaning = new DataCleaning();
                        BeanUtil.copyPropertiesExcludeNullAndEmpty(o, cleaning);
                        cleaning.setBatchNo(batchNo);
                        cleaning.setUserId(userId);
                        try {
                            Result<DataCleaning> saveResult = add(cleaning);
                            if (!saveResult.isSuccess()) {
                                importFailList.add(o);
                            }
                        } catch (Exception e) {
                            log.error("导入数据清理保存异常！", e);
                            importFailList.add(o);
                            result.invokeFail("导入数据清理保存异常！");
                        }
                    });
                }
            }
            result.setData(importFailList);
            return result;
        }
    }

    public Result<DataCleaning> add(DataCleaning req) {
        return new Result<DataCleaning>().invokeSuccess();
    }

}
